home *** CD-ROM | disk | FTP | other *** search
- /*
- File: SnapshotSample.c
-
- Contains: Code for saving and restoring desktop icons.
-
- Written by: Quinn "The Eskimo!"
-
- Copyright: © 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
- */
-
- /*
- This sample, when run the first time, creates a
- snapshot file in the Preferences folder which contains a list
- of the names and locations fo the items on the
- desktop.
-
- Running the sample again will read the snapshot
- file and tell the Finder to position the items
- at the locations read from the snapshot file.
-
- Sample does not read/set location of Trash,
- nor of mounted volumes.
-
- Sample is provided as is... I didn't get much
- chance to test beyond the standard, "oh, this
- works!" stage.
-
- The original Pascal version was written by
- Quinn "The Eskimo!" and released as a Freeware
- utility. This DTS sample was created by
- Deborah Grits. This version was tidied up
- and released by Quinn "The Eskimo!".
-
- Oh what a tangled web we weave...
- */
-
- #include <AppleEvents.h>
- #include <Errors.h>
- #include <Events.h>
- #include <Fonts.h>
- #include <Gestalt.h>
- #include <Memory.h>
- #include <Menus.h>
- #include <OSUtils.h>
- #include <QDOffscreen.h>
- #include <QuickDraw.h>
- #include <Resources.h>
- #include <Script.h>
- #include <ToolUtils.h>
- #include <Windows.h>
-
- //////////////////////////////////////////////////////////////////////////
- // Basic Utilities
-
- static OSErr FindProcessByTypeAndCreator(OSType typeToFind, OSType creatorToFind, ProcessSerialNumber *processSN)
- // Runs through the process list looking for the indicated application.
- {
- OSErr err;
- ProcessInfoRec infoRecToFill;
-
- err = noErr;
- processSN->lowLongOfPSN = kNoProcess;
- processSN->highLongOfPSN = kNoProcess;
- infoRecToFill.processInfoLength = sizeof(ProcessInfoRec);
- infoRecToFill.processName = nil;
- infoRecToFill.processAppSpec = nil;
- do {
- err = GetNextProcess(processSN);
- if (err == noErr) {
- GetProcessInformation(processSN, &infoRecToFill);
- }
- } while ((infoRecToFill.processSignature != creatorToFind || infoRecToFill.processType != typeToFind) ||
- err != noErr);
-
- return(err);
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Global Types
-
- // The snapshot file is made up of records of SnapRecord type.
- // An empty record (ie with name == "") is used to indicate
- // the end of the file.
-
- typedef struct
- {
- Str63 name;
- Point loc;
- } SnapRecord, *SnapRecordPtr, **SnapRecordHandle;
-
-
- //////////////////////////////////////////////////////////////////////////
- // Global Variables
-
- // Used to tell the main event loop to quit.
-
- static Boolean gQuit = false;
-
- // An empty AppleEvent Descriptor.
-
- const static AEDesc gNullDesc = {typeNull, nil};
-
- //////////////////////////////////////////////////////////////////////////
- // Restoring Snapshots
-
- static OSErr SetItemPosition(Str255 fname, Point dest, AEDesc *setDataEvent)
- // Sends an AppleEvent to the targetDesc (which should target the Finder)
- // to set the position of the item whose name is fname to the position dest.
- {
- OSErr err;
- AEDesc fileNameDesc = gNullDesc;
- AEDesc rootDesc = gNullDesc;
- AEDesc propertyDescriptor = gNullDesc;
- AEDesc objParentDesc = gNullDesc;
- AEDesc objDesc = gNullDesc;
- AEDesc reply = gNullDesc;
- AEDesc newData = gNullDesc;
- DescType procDescData = 'posn';
-
- err = AECreateDesc(typeChar, &fname[1], fname[0], &fileNameDesc);
-
- // Create objParentDesc to specify the parent object, ie item "xxxx" of application
- if (err == noErr) {
- err = CreateObjSpecifier(cObject, &rootDesc, formName, &fileNameDesc, false, &objParentDesc);
- }
-
- // Create propertyDescriptor to hold the property specifier, ie position
- if (err == noErr) {
- err = AECreateDesc(typeType, &procDescData, sizeof(procDescData), &propertyDescriptor);
- }
-
- // Create objDesc to reference the data to set, ie position of item "xxx" of application
- if (err == noErr) {
- err = CreateObjSpecifier(cProperty, &objParentDesc, formPropertyID, &propertyDescriptor, false, &objDesc);
- }
-
- // Create on descriptor to hold the new data, ie the new icon position.
- if (err == noErr) {
- err = AECreateDesc(typeQDPoint, (void*)&dest, sizeof(dest), &newData);
- }
-
- // Fill out the parameters, putting the objDesc into the direct object and the new data
- // into the data parameter.
- if (err == noErr) {
- err = AEPutParamDesc(setDataEvent, keyDirectObject, &objDesc);
- }
- if (err == noErr) {
- err = AEPutParamDesc(setDataEvent, keyAEData, &newData);
- }
-
- // Send the event.
- if (err == noErr) {
- err = AESend(setDataEvent, &reply, kAEWaitReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
-
- // Some code that I enable when I'm debugging.
-
- if (false) {
- long errNum;
- Str255 errStr;
- DescType junkType;
- Size realSize;
-
- err = AEGetParamPtr(&reply, keyErrorNumber, typeInteger, &junkType, &errNum, sizeof(errNum), &realSize);
- err = AEGetParamPtr(&reply, keyErrorString, typeChar, &junkType, &errStr[1], 255, &realSize);
- errStr[0] = realSize;
- }
- }
-
- // Clean up all those messy descriptors. Don't you just love AppleEvents (-:
- AEDisposeDesc(&rootDesc);
- AEDisposeDesc(&fileNameDesc);
- AEDisposeDesc(&objParentDesc);
- AEDisposeDesc(&propertyDescriptor);
- AEDisposeDesc(&objDesc);
- AEDisposeDesc(&newData);
- AEDisposeDesc(&reply);
-
- return err;
- }
-
- static OSErr RestoreSnapshot (FSSpec snapFss)
- // Restore the snapshot file specified by snapFss.
- {
- OSErr err;
- ProcessSerialNumber finderPSN;
- AEDesc targetDesc = gNullDesc;
- AEDesc setDataEvent = gNullDesc;
- short snapFileRef;
- Boolean done;
- SnapRecord aSnapRecord;
- long byteCount;
-
- snapFileRef = 0;
-
- // Find the Finder's ProcessSerialNumber and create the targetDesc for it.
- err = FindProcessByTypeAndCreator('FNDR', 'MACS', &finderPSN);
- if (err == noErr) {
- err = AECreateDesc(typeProcessSerialNumber, (Ptr)&finderPSN, sizeof(finderPSN), &targetDesc);
- }
- // Create the AppleEvent.
- if (err == noErr) {
- err = AECreateAppleEvent(kAECoreSuite, kAESetData, &targetDesc,
- kAutoGenerateReturnID, kAnyTransactionID, &setDataEvent);
- }
-
- // Open the file.
- if (err == noErr) {
- err = FSpOpenDF(&snapFss, fsRdPerm, &snapFileRef);
- }
- if (err == noErr) {
-
- // Read the records in the file, repositioning the icons as we go.
- done = false;
- do {
- byteCount = sizeof(SnapRecord);
- err = FSRead(snapFileRef, &byteCount, (void*) &aSnapRecord);
-
- if (err == noErr) {
- // We're done if we hit the empty string.
- done = (aSnapRecord.name[0] == 0);
-
- if (!done) {
- // Reposition the icon.
- err = SetItemPosition(aSnapRecord.name, aSnapRecord.loc, &setDataEvent);
- }
- }
- } while (!done);
- }
-
- if (err == eofErr) {
- err = noErr;
- }
-
- // clean up
- if (snapFileRef != 0) {
- (void) FSClose(snapFileRef);
- }
- AEDisposeDesc(&setDataEvent);
- AEDisposeDesc(&targetDesc);
-
- return err;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Creating Snapshots
-
- static OSErr WriteFileRecord(short snapFileRef, Str63 itemName, Point itemPosition)
- // Add a new record to the snapshot file.
- {
- OSErr err;
- SnapRecord aSnapRecord;
- long byteCount;
-
- BlockMoveData(itemName, aSnapRecord.name, sizeof(aSnapRecord.name));
- aSnapRecord.loc = itemPosition;
-
- byteCount = sizeof(SnapRecord);
- err = FSWrite(snapFileRef, &byteCount, (void*) &aSnapRecord);
-
- return err;
- }
-
- static OSErr CreateSnapshotFile(FSSpec snapFss)
- // Add the positions for the icons on the desktop to the snapshot file snapFss.
- {
- OSErr err;
- short snapFileRef;
- short deskVRefNum;
- long deskDirID;
- CInfoPBRec pb;
- short fileIndex;
- Point folderOrigin;
- Point itemPosition;
- Str63 itemName;
- UInt32 systemVersion;
-
- snapFileRef = 0;
-
- // Find the desktop folder.
- err = FindFolder(kOnSystemDisk, kDesktopFolderType, true, &deskVRefNum, &deskDirID);
-
- // Get the origin for the desktop folder.
- pb.dirInfo.ioNamePtr = nil;
- pb.dirInfo.ioDrDirID = deskDirID;
- pb.dirInfo.ioVRefNum = deskVRefNum;
- pb.dirInfo.ioFDirIndex = -1; // get information about ioDirID
- err = PBGetCatInfoSync(&pb);
- if (err == noErr) {
- folderOrigin.h = 0;
- folderOrigin.v = 0;
- if (Gestalt(gestaltSystemVersion, (long *) &systemVersion) != noErr || systemVersion < 0x0800) {
- // Evil fudge factor is needed for Finder 7.x. Finder 8.0 does not fudge.
- folderOrigin.v = folderOrigin.v - 20;
- }
- }
-
- // Open up the snapshot file.
- if (err == noErr) {
- err = FSpOpenDF(&snapFss, fsRdWrPerm, &snapFileRef);
- }
-
- // Loop through each file in the folder, adding it to the snapshot file.
- if (err == noErr) {
- fileIndex = 1;
- do {
- pb.dirInfo.ioNamePtr = (StringPtr) itemName;
- pb.dirInfo.ioDrDirID = deskDirID;
- pb.dirInfo.ioVRefNum = deskVRefNum;
- pb.dirInfo.ioFDirIndex = fileIndex;
- err = PBGetCatInfoSync(&pb);
- if (err == noErr) {
- itemPosition = pb.hFileInfo.ioFlFndrInfo.fdLocation;
- SubPt(folderOrigin, &itemPosition);
- err = WriteFileRecord(snapFileRef, itemName, itemPosition);
- }
- fileIndex += 1;
- } while (err == noErr);
-
- // Write the sentinel to the end of the file.
- if (err == fnfErr) {
- itemName[0] = 0;
- itemPosition.h = 0;
- itemPosition.v = 0;
- err = WriteFileRecord(snapFileRef, itemName, itemPosition);
- }
- }
-
- // Clean up.
- if (snapFileRef != 0) {
- (void) FSClose(snapFileRef);
- }
-
- return err;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Main Line
-
- static void InitToolbox()
- // Standard Macintosh toolbox init.
- {
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- MaxApplZone();
-
- MoreMasters();
- MoreMasters();
- MoreMasters();
-
- InitCursor();
- FlushEvents(0, everyEvent);
- }
-
- void main(void)
- // The application's main entry point.
- {
- OSErr err;
- FSSpec snapFss;
- long gestaltResponse;
-
- // First, a quick check to make sure we have Scriptable Finder. If we don't
- // we bail quickly.
-
- if ((Gestalt(gestaltFinderAttr, &gestaltResponse) != noErr) || ((gestaltResponse & (1 << gestaltOSLCompliantFinder)) == 0)) {
- DebugStr("\pWhoops, no Scriptable Finder.");
- ExitToShell();
- }
-
- // Now bring up the standard Mac toolbox.
- InitToolbox();
-
- // Find the Preferences folder.
- err = FindFolder(kOnSystemDisk, kPreferencesFolderType, false, &(snapFss.vRefNum), &(snapFss.parID));
-
- if (err == noErr) {
-
- // Open the snapshot file in the Preferences folder.
- // Should get this from a resource, of course.
-
- (void) FSMakeFSSpec(snapFss.vRefNum, snapFss.parID, "\pDesktop Snap", &snapFss);
- err = FSpCreate(&snapFss, 'FRøG', 'FRøG', 0);
-
- if (err == dupFNErr) { // If we already have a snapshot file,
- err = RestoreSnapshot(snapFss); // restore icon positions,
- } else if (err == noErr) { // otherwise make a snapshot file.
- // Create the snapshot file for the desktop
- err = CreateSnapshotFile(snapFss);
- }
- }
-
- if (err != noErr) {
- DebugStr("\pSnapshotter failed.");
- }
- }
-